
class Promise {
    constructor(exector) {
        this.PromiseState = 'pendding'
        this.PromiseResult = undefined
        const _this = this
        this.callbacks = []
        function resolve(data) {
            if (_this.PromiseState !== 'pendding') return
            _this.PromiseResult = data
            _this.PromiseState = 'fulfilled'

            _this.callbacks.forEach(item => {
                item.onResolve(data)
            })
        }
        function reject(data) {
            if (_this.PromiseState !== 'pendding') return
            _this.PromiseResult = data
            _this.PromiseState = 'rejected'

            _this.callbacks.forEach(item => {
                item.onReject(data)
            })
        }
        try {
            exector(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }
    then(onResolve, onReject) {
        const _this = this
        return new Promise((resolve, reject) => {
            if (typeof onReject !== 'function') {
                onReject = reason => {
                    throw reason
                }
            }
            if (typeof onResolve !== 'function') {
                onResolve = value => value
            }
            function callback(type) {
                try {
                    let result = type(_this.PromiseResult)
                    if (result instanceof Promise) {
                        result.then(v => { resolve(v) }, r => { reject(r) })
                    } else {
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            }
            if (this.PromiseState === 'fulfilled') {
                callback(onResolve)
            }
            if (this.PromiseState === 'rejected') {
                callback(onReject)
            }
            if (this.PromiseState === 'pendding') {
                this.callbacks.push({
                    onResolve: function () {
                        callback(onResolve)
                    }, onReject: function () {
                        callback(onReject)
                    }
                })
            }
        })
    }
    catch(onReject) {
        return this.then(undefined, onReject)

    }
    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(v => { resolve(v) }, r => { reject(r) })
            } else {
                resolve(value)
            }
        })
    }
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    static all(promises) {
        return new Promise((resolve, reject) => {
            let count = 0
            let arr = []
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    count++
                    arr[i] = v
                    if (count === promises.length) {
                        resolve(arr)
                    }
                }, r => {
                    reject(r)
                })
            }
        })
    }
    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })

    }
}

